package sourceproxy 
{
	import adobe.utils.CustomActions;
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.DisplayObject;
	import flash.display.Loader;
	import flash.display.LoaderInfo;
	import flash.display.MovieClip;
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.net.LocalConnection;
	import flash.net.URLRequest;
	import flash.system.ApplicationDomain;
	import flash.system.LoaderContext;
	import flash.utils.getDefinitionByName;
	import flash.utils.getQualifiedClassName;
	import utils.HashMap;
	import utils.Tools;
	
	/**
	 * ...
	 * @author jun
	 */
	public class ResourceProxy
	{
		private const load_max:uint = 5;	//并行加载最大数
		static private var map:HashMap = new HashMap();;
		
		private var queueList:Array;	//待加载资源
		
		private var loadList:Array; //记录正在加载中的数量
		private var loadedUrlList:Array;
		private var customRootList:Array;
		
		private var fileTotal:int;//文件总数
		private var fileLoaded:int; //已加载数
		
	
		
		private var onCompleteListen:Array;
		private var onProgressListen:Array;
		
		private static var _instance:ResourceProxy;
		public static function instance():ResourceProxy
		{
			if (_instance == null)
			{
				_instance = new ResourceProxy();
			}
			return _instance;
		}
		
		
		public function ResourceProxy() 
		{
			
			queueList = new Array();
			loadList = new Array();
			loadedUrlList = new Array();
			customRootList = new Array();
			fileTotal = 0;
			fileLoaded = 0;
			onCompleteListen = new Array();
			onProgressListen = new Array();
		}
		
		public function push(url:String, customRoot:String = null ):void
		{
			if (map.get(url) != null)
			{
				return;
			}
			if (queueList.indexOf(url) == -1)
			{
				queueList.push(url);
				customRootList.push(customRoot);
				fileTotal++;
			}
		}
		
		static public function get(url:String):*
		{
			return map.get(url);
		}
		
		
		static public function tryClass(name:String):Object
		{
			try
			{
				var classReference:Object = getDefinitionByName(name);
				if (!classReference) return null;
				return classReference;
			}
			catch (e:Error)
			{
				
			}
			return null;
			//if (ApplicationDomain.currentDomain.hasDefinition(name))
			//{
				//var classReference:Object = ApplicationDomain.currentDomain.getDefinition(name);
				//if (!classReference) return null;
				//return classReference;
			//}
			
		
		}
		
		static public function getBitmapData(url:String):BitmapData
		{
			var item:* = get(url) as BitmapData;
			if (item) return item;
			
			item = get(url) as LoaderInfo;
			if (item)
			{
				if (MovieClip(item.content).totalFrames == 1)
				{
					var tempBmp:BitmapData = new BitmapData(item.content.width, item.content.height);
					tempBmp.draw(item.content);
					remove(url);
					map.put(url, tempBmp);
					return tempBmp;
				}
			}
			
			var classRef:Object = tryClass(url);
			if (classRef)
			{
				item = new classRef();
				if (item is BitmapData)
				{
					map.put(url, item);
					return item;
				}
			}
			
			return null;
			
			
		}
		
		static public function getMovieClip(url:String):MovieClip
		{
			var loaderInfo:LoaderInfo = get(url) as LoaderInfo;
			if (loaderInfo)
			{
				return loaderInfo.content as MovieClip;
			}
			return null;
		}
		
		public function load(completeCallBack:Function=null):void
		{
			onComplete = completeCallBack;
			if (fileLoaded >= fileTotal)
			{
				completed();
				return;
			}
			check();
		}
		
		public function realLoad(url:String,customRoot:String):void
		{
			var loader:Loader = new Loader();
			var root:String = MangMeiMgr.RESOURCE_ROOT;
			if (customRoot != "") root = customRoot;
			
			var urlRequest:URLRequest = new URLRequest(root + url);
			loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoadComplete);
			loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, onIOErrorHandler);
			loader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, onProgressHandler);
			
			loader.load(urlRequest, new LoaderContext(false, ApplicationDomain.currentDomain));
			loadList.push(loader);
			loadedUrlList.push(url);
		}
		
		private function onProgressHandler(e:ProgressEvent):void 
		{
			//trace("正在加载" + fileLoaded + "/" + fileTotal +(e.bytesLoaded / e.bytesTotal) * 100 +"%"); 
		}
		
		private function onIOErrorHandler(e:IOErrorEvent):void 
		{
			trace(e.text);
		}
		
		private function onLoadComplete(e:Event):void 
		{
			var loaderInfo:LoaderInfo = e.target as LoaderInfo;
			loaderInfo.removeEventListener(Event.COMPLETE, onLoadComplete);
			loaderInfo.removeEventListener(IOErrorEvent.IO_ERROR, onIOErrorHandler);
			loaderInfo.removeEventListener(ProgressEvent.PROGRESS, onProgressHandler);
			
			
			var index:int = loadList.indexOf(loaderInfo.loader);
			if (index >= 0)
			{
				
				var loader:Loader=loadList.splice(index, 1)[0] as Loader;
				if (loaderInfo.contentType.indexOf("flash") >= 0)
				{
					map.put(loadedUrlList[index], loaderInfo);
				}
				else if (loaderInfo.contentType.indexOf("image") >= 0)
				{
					var target:BitmapData = Bitmap(loaderInfo.content).bitmapData;
					var tempBitmap:BitmapData = new BitmapData(loaderInfo.content.width, loaderInfo.content.height);
					tempBitmap.copyPixels(target,new Rectangle(0,0,target.width,target.height),new Point);
					map.put(loadedUrlList[index], tempBitmap);
					loader.unload();
					loader = null;
				}else
				{
					
				}
				
				loadedUrlList.splice(index, 1);
				customRootList.splice(index, 1);
				fileLoaded++;
				if (fileLoaded >= fileTotal)
				{
					completed();
					
				}
				else
				{
					progress();
				}
				
				check();
			}
		}
		
		private function completed():void
		{
			onCompleteListen.forEach(
				function (item:Function, index:int, array:* ):void
				{
					item&&item();
					//array.splice(index, 1);
				}
			);
			//onCompleteListen.splice(0, onCompleteListen.length);
		}
		
		private function progress():void
		{
			onProgressListen.forEach(
				function (item:Function, index:int, array:Array ):void
				{
					item(fileLoaded,fileTotal);
				}
			);
		}
		
		private function check():void
		{
			if (queueList.length > 0 && loadList.length < load_max)
			{
				var url:String = queueList[0];
				queueList.splice(0, 1);
				var root:String = customRootList.splice(0, 1);
				realLoad(url,root);
				check();
			}
		}
		
		public function set onComplete(complete:Function):void
		{
			var index:int = Tools.getIndexInArray(onCompleteListen, complete);
			if (typeof(complete) =="function")
			{
				if ( index== -1)
					onCompleteListen.push(complete);
			}
			else
			{
				if (index >= 0)
					onCompleteListen.splice(index, 1);
			}
		}
		
		public function set onProgress(progress:Function):void
		{
			var index:int = Tools.getIndexInArray(onProgressListen, progress);
			if (typeof (progress) =="function")
			{
				if ( index== -1)
					onProgressListen.push(progress);
			}
			else
			{
				if (index >= 0)
					onProgressListen.splice(index, 1);
			}
		}
		
		public function removeEventListener(type:String,listener:Function):void
		{
			var index:int;
			if (type == ResourceProxyEventType.COMPLETE)
			{
				index = Tools.getIndexInArray(onCompleteListen, listener);
				if(index>=0)
					onCompleteListen.splice(index, 1);
			}
			else if (type == ResourceProxyEventType.PROGRESS)
			{
				index = Tools.getIndexInArray(onProgressListen, listener);
				if (index >= 0)
					onProgressListen.splice(index, 1);
			}
			
		}
		
		static public function remove(url:String):void
		{
			var temp:*= map.remove(url);
			if (temp is BitmapData)
			{
				BitmapData(temp).dispose();
				temp = null;
			}
			else if (temp is LoaderInfo)
			{
				temp.loader.unloadAndStop(true);
				temp.loader.unload();
				temp = null;
			}
		}
	}

}